<?php
// +-------------------------------------------------------------------------+
// | PHP Version 5                                                           |
// +-------------------------------------------------------------------------+
// | ImaEngine - web development framework                                   |
// | Copyright (c) 2006-2007 Sardar Yumatov <ja.doma@gmail.com>              |
// +-------------------------------------------------------------------------+
// | This library is free software; you can redistribute it and/or modify it |
// | under the terms of the GNU Lesser General Public License as published   |
// | by the Free Software Foundation; either version 2.1 of the License, or  |
// | (at your option) any later version.                                     |
// |                                                                         |
// | This library is distributed in the hope that it will be useful, but     |
// | WITHOUT ANY WARRANTY; without even the implied warranty of              |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                    |
// | See the GNU Lesser General Public License for more details.             |
// |                                                                         |
// | You should have received a copy of the GNU Lesser General Public        |
// | License along with this library; if not, write to the Free Software     |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
// +-------------------------------------------------------------------------+

/**
* Standart template based view object (render).
*
* @package common.view
* @category text-stream
* @version v1.0
* @author Sardar Yumatov <ja.doma@gmail.com>
* @copyright Copyright &copy; 2006-2007 Sardar Yumatov
*
* @PHP5only
*/

if(!defined('PROCESS')) {
	header('HTTP/1.1 404 Not Found');
	die('NotFound');
}

require_once('lib/view/AbstractTextStreamView.php');
require_once('lib/template/AbstractTemplateDocument.php');

/**
 * Standart template based render.
 *
 * This class is able to evaluate template when process-output event with specific label is triggered.
 * The class is ready to use by simple templates that output text and trigger process-output and process-marker
 * events. Other text-stream views that use templates usually extends this class.
 *
 * @author Sardar Yumatov <ja.doma@gmail.com>
 */
class TemplatedTextStreamView extends AbstractTextStreamView implements TemplateDocumentHandler {

	/** Template used to produce the output.
	 * @var AbstractTemplateDocument */
	protected $template;

	/** Label to recognize by <tt>processOutput()</tt> if needed.
	 * @var string */
	protected $label;

	/** Template handler that drives this instance.
	 * May be created on demands, so must be private, use <tt>getTemplateHandler()</tt>
	 * @var TemplatedTextStreamViewTemplateHandler */
	private  $handler;

	/**
	 * Create new templated text-stream view.
	 * If $label is set, then this instance will wait for given label. This makes simple
	 * "glue" templates very easy to use.
	 *
	 * By default the template handler used by this class implements only necessary for the view object
	 * functionality. The chain of hanlders may be set via $basehandler variable.
	 *
	 * @param AbstractTemplateDocument $template used to produce text output, null if template needs to be loaded on demand
	 * @param string $label label to recognize by process-output event or null if none
	 * @param TemplateDocumentHandler $basehandler the handler that will recieve template events if they are not recognized
	 */
	public function __construct($template, $label=null, $basehandler=null) {
		$this->template = $template;
		$this->label = $label;
		$this->handler = new TemplatedTextStreamViewTemplateHandler($this, $basehandler);
	}

	/**
	 * Returns template handler that drives this view object.
	 * @return TemplatedTextStreamViewTemplateHandler
	 */
	public function getTemplateHandler() {
		return $this->handler;
	}

	/**
	 * Process template if internal label is set and is equal to given $label.
	 * If internal label is null an given $label is null (root view), then template will be processed too.
	 * @param string $label label defined in the template, null for the root view
	 * @return void
	 */
	public function processOutput($label) {
		if($label === $this->label) $this->template->processOutput($this->handler);
	}

	/**
	 * Returns list of labels recognized by this object.
	 * Method returns empty array or array with single element if internal label is set.
	 * @return array of string - labels as [label => label]
	 */
	public function getExpectingLabels() {
		$ret = array();
		if(!is_null($this->label)) $ret[$this->label] = $this->label;
		return $ret;
	}
}

/**
 * Template handler that will drive the view object.
 * The purpose of this class to act as a simple template handler and fire events when recognized
 * tags occur in the template.
 *
 * @author Sardar Yumatov <ja.doma@gmail.com>
 */
class TemplatedTextStreamViewTemplateHandler extends AbstractTemplateDocumentHandler {

	/** The view object to drive.
	 * @var TemplatedTextStreamView */
	private $view;

	/**
	 * Enter description here...
	 *
	 * @param TemplatedTextStreamView $view
	 * @param TemplateDocumentHandler $basehandler
	 */
	public function __construct(TemplatedTextStreamView $view, TemplateDocumentHandler $basehandler = null) {
		parent::__construct($basehandler);
		$this->view = $view;
	}

	/**
	 * Returns view object, driven by this handler.
	 * @return TemplatedTextStreamView
	 */
	public function getView() {
		return $this->view;
	}

	/**
	 * Process the template tag.
	 *
	 * This method implements following actions:
	 * 	 - view.output -- fires process-output event
	 *   - view.marker -- firex trigger-marker event
	 *
	 * Both actions accept multiple arguments, only markers with nummeric indexes will be
	 * processed one-by-one.
	 * Examples:
	 *   - {%view.output: content%} -- fires 'content' process-output event
	 *   - {%view.marker: meta head%} -- fires 'meta' and 'head' marker events in that order
	 *
	 * @param AbstractTemplateDocumentBlock $block the current block instance being processed
	 * @param string $action the action name
	 * @param array $markers the list of markers defined by the user
	 * @return boolean true if output should be used, false if output should be discarded
	 */
	public function processTag(AbstractTemplateDocumentBlock $block, $action, $markers) {
		switch($action) {
			case 'view.output': for($i=0; isset($markers[$i]); $i++) $this->view->triggerProcessOutput($markers[$i]); return true;
			case 'view.marker': for($i=0; isset($markers[$i]); $i++) $this->triggerMarker($markers[$i]); return true;
		}
		return parent::processTag($block, $action, $markers);
	}
}

?>